// Connection class implementation

#include <pthread.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include "Connection.h"

int MAXFNAME=50;

Connection::Connection(){
  //Can't use this connection until it's initialized with Connection::init()
  pthread_mutex_init(&Mux,NULL);
  pthread_mutex_init(&sendmux,NULL);
  IP = "";
  Port = -1;
  pubkeyfile=(char*)malloc(sizeof(char)*MAXFNAME);
  setidle();
  Connection::lock(); 
}

Connection::Connection(std::string ip,int port){
  pthread_mutex_init(&Mux,NULL);
  pthread_mutex_init(&sendmux,NULL);
  IP = ip;
  Port = port;
  pubkeyfile=(char*)malloc(sizeof(char)*MAXFNAME);
  setidle();
}

Connection::~Connection(){ }

void Connection::init(std::string ip, int port){
  //Only ever call this right after an empty constructor
  IP=ip;
  Port=port;
  Connection::unlock();
  setidle();
}

char Connection::get_status(){
  char s;
  Connection::lock();
  s=Status;
  Connection::unlock();
  return s;
}

std::string Connection::get_ip(){
  std::string s;
  Connection::lock();
  s=IP;
  Connection::unlock();
  return s;
}

bool Connection::get_leader(){
  bool b;
  printf("Leader=%i\n",Leader);
  Connection::lock();
  b=Leader;
  Connection::unlock();
  return b;
}

int Connection::get_group(){
  int g;
  Connection::lock();
  g=Group;
  Connection::unlock();
  //printf("Getting group! %d\n",g);
  return g;
}

std::string Connection::get_uname(){
  std::string u;
  Connection::lock();
  u=Username;
  Connection::unlock();
  return u;
}

void Connection::setidle(){
  Connection::lock();
  Group=-1;
  Leader=false;
  Status=IDLE;
  Connection::unlock();
}

void Connection::setnewbusy(int group, bool leader){
  Connection::lock();
  Group=group;
  Leader=leader;
  Status=NEWBUSY;
  Connection::unlock();
}

void Connection::setfinished(){
  Connection::lock();
  Status=FINISHED;
  Connection::unlock();
}


void Connection::setbusy(){
  Connection::lock();
  Status=BUSY;
  Connection::unlock();
}

void Connection::setuname(std::string uname){
  Connection::lock();
  Username=uname;
  Connection::unlock();
}

void Connection::kill(){
  Connection::lock();
  Group=-1;
  Leader=false;
  Status=DEAD;
  Connection::unlock();
}

void Connection::print(std::ofstream* file){
  Connection::lock();
  //Format:
  //IP.IP.IP.IP STATUS PORT GROUP LEADER 
  *file <<IP<<" "<<Port<<" "<<Status<<" "<<Group<<" "<<Leader<<"\n";
  Connection::unlock();
}

void Connection::print_scr(){
  Connection::lock();
  //Format:
  //IP.IP.IP.IP STATUS PORT GROUP LEADER 
  std::cout <<IP<<" "<<Port<<" "<<Status<<" "<<Group<<" "<<Leader<<"\n";
  Connection::unlock();
}

void Connection::lock(){
  pthread_mutex_lock(&Mux);
}

void Connection::unlock(){
  pthread_mutex_unlock(&Mux);
}

std::string Connection::get_signature(){
  std::string sig;
  char tmp[20];
  Connection::lock();
  sig = IP;
  sprintf(tmp,"%d",Port);
  sig += tmp;
  Connection::unlock();
  return sig;
}

void Connection::setpubkeyfile(const char* filename){
  Connection::lock();
  pubkeyfile=filename;
  Connection::unlock();
}

const char* Connection::getpubkeyfile(){
  return pubkeyfile;
}

const char* Connection::getshortpubkeyfile(){
  return &(pubkeyfile[5]);
}
